package com.lft.juc02.producterconsumer;

import com.sun.org.apache.bcel.internal.generic.NEW;

/**
 * Function: 		A {@code PC} 线程之间的通信问题：生产者与消费者.<br/>
 * Reason:   		线程交替执行.<br/>
 * A B 操作现一个变量 num = 0
 * A num + 1
 * B num - 1
 * Date:            2021-01-29 15:51<br/>
 * <p>
 * Class Name:      PC<br/>
 * Package Name:    com.lft.juc02.producterconsumer<br/>
 * @author Laifengting / E-mail:laifengting@foxmail.com
 * @version 1.0.0
 * @since JDK 8
 */
public class PC {
	public static void main(String[] args) {
		Date date = new Date();
		new Thread(()->{for(int i = 0; i < 10; i++)date.increment();},"~A~").start();
		new Thread(()->{for(int i = 0; i < 10; i++)date.decrement();},"~B~").start();
		new Thread(()->{for(int i = 0; i < 10; i++)date.increment();},"~C~").start();
		new Thread(()->{for(int i = 0; i < 10; i++)date.decrement();},"~D~").start();
	}
}

/**
 * 资源类——数据
 * 步骤：判断等待——业务——通知
 * /while(有资源){
 * /	等待
 * /}
 * /	业务
 * /	通知
 * /
 */
class Date {
	private int number = 0;
	
	// +1
	public synchronized void increment() {
		// 判断(不能用 if 判断，多线程时会出现虚假唤醒)
		while (number != 0) {
			// 等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		// 业务
		number++;
		System.out.println(Thread.currentThread().getName() + " 生产了第 " + number + " 个产品！");
		//通知其他线程，+1 完成。
		this.notifyAll();
	}
	
	// -1
	public synchronized void decrement(){
		// 判断(不能用 if 判断，多线程时会出现虚假唤醒)
		while (number == 0) {
			// 等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		// 业务
		number--;
		System.out.println(Thread.currentThread().getName() + " 消费了 " + number + " 号产品！");
		//通知其他线程，-1 完成。
		this.notifyAll();
	}
}
